
package com.irdstudio.efp.batch.service.impl.hjwp;

import com.irdstudio.basic.framework.core.bean.TxtFileLoadBean;
import com.irdstudio.basic.framework.core.constant.DblStEnum;
import com.irdstudio.basic.framework.core.util.AccLoanStatusUtils;
import com.irdstudio.basic.framework.core.util.StringUtil;
import com.irdstudio.basic.framework.core.util.TimeUtil;
import com.irdstudio.basic.framework.core.util.TxtFileLoadPlugin;
import com.irdstudio.efp.batch.service.facade.hjwp.SynAccloanProcessService;
import com.irdstudio.efp.console.common.YedConstantSet;
import com.irdstudio.efp.console.common.psd.PsdConstantSet;
import com.irdstudio.efp.console.service.facade.PrdInfoService;
import com.irdstudio.efp.console.service.facade.PubSysInfoService;
import com.irdstudio.efp.console.service.vo.PrdInfoVO;
import com.irdstudio.efp.limit.service.facade.LmtPrdContService;
import com.irdstudio.efp.loan.service.facade.AccLoanService;
import com.irdstudio.efp.loan.service.facade.AccoutErroTempService;
import com.irdstudio.efp.loan.service.facade.LoanRepayPlanService;
import com.irdstudio.efp.loan.service.facade.SyncLoanDiffLogService;
import com.irdstudio.efp.loan.service.vo.*;
import com.irdstudio.efp.nls.common.constant.AcctStEnum;
import com.irdstudio.efp.nls.service.facade.NlsApplyInfoService;
import com.irdstudio.efp.nls.service.facade.PsdSendTaxRecordService;
import com.irdstudio.efp.nls.service.facade.UpdateLmtPrdContService;
import com.irdstudio.efp.nls.service.facade.sx.NlsCreditInfoService;
import com.irdstudio.efp.nls.service.vo.NlsApplyInfoVO;
import com.irdstudio.efp.nls.service.vo.PsdSendTaxRecordVO;
import jdk.jfr.events.ThrowablesEvent;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.io.File;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 晚批同步互金借据、还款计划、还款信息数据-贷款台账同步
 *
 * @version 0.1
 */
@Service("synAccloanProcessService")
public class SynAccloanProcessServiceImpl implements SynAccloanProcessService, SynFileDataInterface {

    private static Logger logger = LoggerFactory.getLogger(SynAccloanProcessServiceImpl.class);

    //五级分类码值转换
    private static final HashMap<String, String> riskLevelMap = new HashMap();

    //还款方式
    private static final HashMap<String, String> repayModelMap = new HashMap();


    static {
        //五级分类
        //正常 关注 次级 可疑 损失
        riskLevelMap.put("01", "10");
        riskLevelMap.put("02", "20");
        riskLevelMap.put("03", "30");
        riskLevelMap.put("04", "40");
        riskLevelMap.put("05", "50");

        //还款方式
//        FB01	到期还本	4	按频率付息、一次还本
//        FB02	分期等额本金	2	等额本金
//        FB03	分期等额本息	1	等额本息
//        FB99	其他
//        FB04	一次还本付息	3	一次还本付息
        repayModelMap.put("4", "101");
        repayModelMap.put("2", "201");
        repayModelMap.put("1", "102");
        repayModelMap.put("3", "203");
    }

    @Autowired
    @Qualifier("accLoanService")
    private AccLoanService accLoanService;

    @Autowired
    @Qualifier("accLoanRepayPlanService")
    private LoanRepayPlanService accLoanRepayPlanService;

    @Autowired
    @Qualifier("nlsApplyInfoService")
    private NlsApplyInfoService nlsApplyInfoService;

    @Autowired
    @Qualifier("prdInfoService")
    private PrdInfoService prdInfoService;

    @Autowired
    private PubSysInfoService pubSysInfoService;

    @Autowired
    private UpdateLmtPrdContService updateLmtPrdContService;

    @Autowired
    private SyncLoanDiffLogService syncLoanDiffLogService;

    @Autowired
    private PsdSendTaxRecordService psdSendTaxRecordService;

    //@Value("${sed.loanFilePath}")
    private String loanFilePath = "/home/ocmuser/share/infile/psd/syncfile/";

    //@Value("${sed.accLoanFileNameDat}")
    private String fileNameOfDat = "idl_dm_loan_dubil_basic_info_i.$date$.dat";

    //@Value("${sed.accLoanFileNameOk}")
    private String fileNamOfOk = "idl_dm_loan_dubil_basic_info_i.$date$.ok";

    private PrdInfoVO currentPrdInfo = null;

    private String openDay;

    /**
     * 批次开始执行时间
     */
    private Date batchRunDate;

    /**
     * 批次日期
     */
    private String batchSubDate;

    /**
     * 需要更新额度信息的用信流水号
     */
    private ArrayList<String> updateLmtApplySeqs = new ArrayList<>();

    @Override
    public Boolean syncAccloan(String subDate) throws Exception {
        try {
            //subDate = "2025-02-18";
            logger.info("批次时间：[{}]的互贷款台账同步批次开始运行", subDate);
            updateLmtApplySeqs.clear();
            batchRunDate = new Date();
            batchSubDate = subDate;
            PrdInfoVO param = new PrdInfoVO();
            param.setPrdId(PsdConstantSet.prdId);
            param.setPrdCode(PsdConstantSet.prdId);
            currentPrdInfo = prdInfoService.queryByPrdCode(param);
            if (Objects.isNull(currentPrdInfo)) {
                logger.info("批次时间：[{}]的互贷款台账同步批次获取到的产品为空", subDate);
                throw new Exception("获取到的产品为空");
            }
            //查询当前的账务日期
            openDay = pubSysInfoService.getOpenday("1001");
            logger.info("批次时间：[{}]的互贷款台账同步批次获取到的openday={}", subDate, openDay);
            if (StringUtils.isEmpty(openDay)) {
                throw new Exception("获取openday为空");
            }
            String fileUrl = loanFilePath + getCurrentBatchFileName(fileNameOfDat, subDate);
            //判断文件是否存在
            if (!new File(fileUrl).exists()) {
                logger.info("批次时间：[{}]的互贷款台账同步批次文件[{}]不存在", subDate, fileUrl);
                throw new Exception("数据文件不存在");
            }
            if (getOkFileDataNum(loanFilePath, fileNamOfOk, subDate) < 1) {
                logger.info("获取到的ok文件中的文件数据条数为空，不做处理");
                return Boolean.TRUE;
            }
            //校验ok文件
            if (!validateOkFile(getFileNum(fileUrl), loanFilePath, fileNamOfOk, subDate)) {
                return Boolean.FALSE;
            }
            TxtFileLoadPlugin txtFileLoadPlugin = new TxtFileLoadPlugin(fileUrl, "\u0002", "UTF-8", 0, 1000);
            List<TxtFileLoadBean> loanList = txtFileLoadPlugin.run(new SynAccLoanVO());
            dueData(loanList, subDate);
            if (loanList.size() != 0) {
                while (!loanList.get(loanList.size() - 1).isReadedComplete) {
                    txtFileLoadPlugin.setFirstRead(false);
                    loanList = txtFileLoadPlugin.run(new SynAccLoanVO());
                    if (loanList.size() == 0) {
                        break;
                    }
                    dueData(loanList, subDate);
                }
            }
            //处理完成后需要更新还款计划的总期数字段
            //accLoanRepayPlanService.fixInitTerm(PsdConstantSet.prdId);
            //处理完成后需要更新额度信息
            logger.info("批次时间：[{}]的互贷款台账同步批次---恢复额度", subDate);
            updateLimit(updateLmtApplySeqs);
            return Boolean.TRUE;
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("批次时间：[{}]的互贷款台账同步批次发生异常：【{}】", batchSubDate, e.getMessage());
            throw e;
        }
    }

    private ArrayList<AccLoanVO> insertOrUpdateAccloanVOs = new ArrayList<>();
    /**
     * 差异记录
     */
    private ArrayList<SyncLoanDiffLogVO> syncLoanDiffLogVOS = new ArrayList<>();

    /**
     * 处理数据
     *
     * @param list
     * @param sub_date_date
     * @throws Exception
     */
    public void dueData(List<TxtFileLoadBean> list, String sub_date_date) throws Exception {
        //清空
        insertOrUpdateAccloanVOs.clear();
        syncLoanDiffLogVOS.clear();
        //数据为空
        if (list == null) {
            return;
        }
        //数据为空
        if (list.isEmpty()) {
            return;
        }
        //根据文件数据获取当前需要处理的借据号（账户主键）
        List<String> ids = list.stream().map(a -> ((SynAccLoanVO) a).getId()).distinct().collect(Collectors.toList());
        // 根据借据号获取借据信息
        List<AccLoanVO> accLoanVOList = accLoanService.queryByBillNos(ids);
        Map<String, AccLoanVO> accLoanVOMap = new HashMap<>();
        //如果获取到的借据信息列表为空，那么新建一个空list
        if (accLoanVOList != null && accLoanVOList.size() > 0) {
            //转成map
            accLoanVOMap = accLoanVOList.stream().collect(Collectors.toMap(AccLoanVO::getBillNo, a -> a, (K1, K2) -> K1));
        }
        //查询逾期的最小期数的还款计划
        List<LoanRepayPlanVO> loanRepayPlanVOS = accLoanRepayPlanService.queryMinOverdueStmtDates(ids);
        Map<String, LoanRepayPlanVO> loanRepayPlanVOMap = loanRepayPlanVOS.stream().collect(Collectors.toMap(LoanRepayPlanVO::getRefNbr, b -> b, (K3, K4) -> K3));
        for (int i = 0; i < list.size(); i++) {
            SynAccLoanVO sedSynAccLoanVO = (SynAccLoanVO) list.get(i);
            AccLoanVO accLoanVO = accLoanVOMap.get(sedSynAccLoanVO.getId());
            if (Objects.isNull(accLoanVO)) {
                logger.info(sedSynAccLoanVO.getId() + "在本地不存在");
                //保存新增数据到差异表
                insertDiffLog("1", sedSynAccLoanVO, accLoanVO, "借据信息在网贷不存在");
                continue;
            }
            if ("1".equals(sedSynAccLoanVO.getSendTaxFlag())) {
                //批扣成功的记录需要插入数据到回写记录表
                insertTaxRecord(sedSynAccLoanVO, sub_date_date);
            }
            if (!checkDate(accLoanVO,sedSynAccLoanVO)) {
                continue;
            }
            try {
                // 保存更新数据到差异表
                insertDiffLog("2", sedSynAccLoanVO, accLoanVO,"正常更新");
                // 账务日期
                //accLoanVO.setBizDate(LocalDate.parse(openDay, DateTimeFormatter.ofPattern("yyyy-MM-dd")).plusDays(-1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                setBizDate(sub_date_date,accLoanVO);
                //支用合同号
                accLoanVO.setApplySeq(sedSynAccLoanVO.getContNo());
                accLoanVO.setLoanSeq(sedSynAccLoanVO.getLoanSeq());
                accLoanVO.setDistrNo(sedSynAccLoanVO.getDistrNo());
                //客户号--客户编号---客户编号不做更改
                //accLoanVO.setCusId(sedSynAccLoanVO.getCusId());
                //借据余额--借据余额
                accLoanVO.setLoanBalance(sedSynAccLoanVO.getLoanBalance());
                //未到期本金
                //逾期本金
                accLoanVO.setOverdueBalance(sedSynAccLoanVO.getOverduePrincipal());
                //贷款起始日--贷款起始日
                accLoanVO.setLoanStartDate(sedSynAccLoanVO.getLoanStartDate());
                //贷款终止日
                accLoanVO.setLoanEndDate(sedSynAccLoanVO.getLoanEndDate());
                //原到期日期
                accLoanVO.setOrigExpiDate(sedSynAccLoanVO.getLoanEndDate());
                //利息基准利率
                if (!Objects.isNull(sedSynAccLoanVO.getRulingIr())) {
                    accLoanVO.setRulingIr(sedSynAccLoanVO.getRulingIr().divide(BigDecimal.valueOf(100), 8, BigDecimal.ROUND_HALF_UP));
                }
                //利息执行年利率
                if (!Objects.isNull(sedSynAccLoanVO.getRealityIrY())) {
                    accLoanVO.setRealityIrY(sedSynAccLoanVO.getRealityIrY().divide(BigDecimal.valueOf(100), 8, BigDecimal.ROUND_HALF_UP));
                }
                // 累计结息-利息
                accLoanVO.setReceIntCumu(sedSynAccLoanVO.getRaceIntCumu());
                // 累计结息利息- 逾期利息
                //BigDecimal actualIntCumu = Optional.ofNullable(sedSynAccLoanVO.getRaceIntCumu()).orElse(BigDecimal.ZERO).subtract(Optional.ofNullable(sedSynAccLoanVO.getOverdueInterest()).orElse(BigDecimal.ZERO));
                //accLoanVO.setActualIntCumu(actualIntCumu);
                // 欠息累计
                accLoanVO.setDelayIntCumu(sedSynAccLoanVO.getOverdueInterest());
                // 台账状态
                accLoanVO.setAccountStatus(AccLoanStatusUtils.transferAccStatusByHj(sedSynAccLoanVO.getAcctStatus(), sedSynAccLoanVO.getAccountStatus()));
                // w:正常贷款余额
                accLoanVO.setNormalBalance((sedSynAccLoanVO.getLoanBalance() == null ? BigDecimal.ZERO : sedSynAccLoanVO.getLoanBalance()).subtract(sedSynAccLoanVO.getOverduePrincipal() == null ? BigDecimal.ZERO : sedSynAccLoanVO.getOverduePrincipal()));
                // w:拖欠本金
                accLoanVO.setUnpdPrinBal(sedSynAccLoanVO.getLoanBalance());
                //设置逾期相关信息
                setOverdueInfo(loanRepayPlanVOMap, sedSynAccLoanVO, accLoanVO);
                // 结算日期-结清日期
                setSettlDate(sedSynAccLoanVO, accLoanVO);
                // 利率类型 caoxin：互金不送了
                //accLoanVO.setIntRateType(sedSynAccLoanVO);
                // 利率增量选项 1 浮动值  2 浮动比 不确定
                //accLoanVO.setIntRateIncOpt();
                // 固定的罚息率 罚息执行年利率
                if (!Objects.isNull(sedSynAccLoanVO.getFixedRateIrY())) {
                    accLoanVO.setPrinFixedRate(sedSynAccLoanVO.getFixedRateIrY().divide(BigDecimal.valueOf(100), 8, BigDecimal.ROUND_HALF_UP));
                }
                // h:累计结息复利 w:应收复利累计
                accLoanVO.setUnpdArrPrnBal(sedSynAccLoanVO.getRaceReIntCumu());
                // 实收拖欠本金的罚息 累计结息罚息-逾期罚息
                //BigDecimal actArrsIntBal = Optional.ofNullable(sedSynAccLoanVO.getUnpdArrsPrnBa1()).orElse(BigDecimal.ZERO).subtract(Optional.ofNullable(sedSynAccLoanVO.getOverdueCharge()).orElse(BigDecimal.ZERO));
                //accLoanVO.setActArrsIntBal(actArrsIntBal);
                //  实收复利  累计结息复利-逾期复利
                //BigDecimal actArrPrnBal = Optional.ofNullable(sedSynAccLoanVO.getRaceReIntCumu()).orElse(BigDecimal.ZERO).subtract(Optional.ofNullable(sedSynAccLoanVO.getCompIntRateInc()).orElse(BigDecimal.ZERO));
                //accLoanVO.setActArrPrnBal(actArrPrnBal);
                // 还款日
                accLoanVO.setReturnDate(sedSynAccLoanVO.getRepayDate());
                // 拖欠本金的罚息(应收未收)
                accLoanVO.setUnpdArrsIntBal1(sedSynAccLoanVO.getOverdueCharge());
                // h:逾期复利 w:应收未收的复利
                accLoanVO.setUnpdArrPrnBal1(sedSynAccLoanVO.getCompIntRateInc());
                // 欠息累计-累计结息 罚息
                accLoanVO.setDelayIntCumu1(sedSynAccLoanVO.getUnpdArrsPrnBa1());
                // 还款方式
                String repayMode = repayModelMap.get(sedSynAccLoanVO.getRepaymentMode());
                if (StringUtil.isNotEmpty(repayMode)) {
                    accLoanVO.setRepaymentMode(repayMode);
                }
                // 五级分类
                if (!"2".equals(accLoanVO.getManualIdt())) {
                    accLoanVO.setClaPre(accLoanVO.getCla());
                    accLoanVO.setCla(riskLevelMap.get(sedSynAccLoanVO.getCla()));
                    accLoanVO.setClaDatePre(accLoanVO.getClaDate());
                    accLoanVO.setClaDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                }
                // 逾期天数
                accLoanVO.setOverdueDays(StringUtils.isEmpty(sedSynAccLoanVO.getOveerdueDay()) ? BigDecimal.ZERO : new BigDecimal(sedSynAccLoanVO.getOveerdueDay()));
                // 当前期数 取还款计划表开始日期《当前日期《到期日期 对应记录的期数
                accLoanVO.setCurrTerm(new BigDecimal(getCurrentTerm(accLoanVO)));
                // 最后修改日期
                accLoanVO.setLastUpdateTime(TimeUtil.getCurrentDateTime());

                insertOrUpdateAccloanVOs.add(accLoanVO);

            } catch (Exception e) {
                // 如果发生单笔异常 继续处理下一笔数据  记录借据号
                logger.error("【"+batchSubDate+"】号文件【晚批】更新借据"+accLoanVO.getBillNo()+"发生异常，信息为：",e);
                continue;
            }
        }
        if (insertOrUpdateAccloanVOs.size() > 0) {
            accLoanService.insertOrUpdatePsd(insertOrUpdateAccloanVOs);
            updateLmtApplySeqs.addAll(insertOrUpdateAccloanVOs.stream().map(a -> a.getApplySeq()).distinct().collect(Collectors.toList()));
        }
        if (syncLoanDiffLogVOS.size() > 0) {
            syncLoanDiffLogService.batchInsert(syncLoanDiffLogVOS);
        }
    }

    /**
     * 设置结清日期
     * 如果结算日期不为空，则做如下操作：
     * 1、并且互金-结算日期小于等于贷款终止日，则直接赋值
     * 2、（互金-结算日期）-1天 落值
     * @param sedSynAccLoanVO
     * @param accLoanVO
     */
    private void setSettlDate(SynAccLoanVO sedSynAccLoanVO, AccLoanVO accLoanVO) {
        if (StringUtils.isNotEmpty(sedSynAccLoanVO.getSettlementDate())) {
            try {
                //int i = TimeUtil.compareDates(sedSynAccLoanVO.getSettlementDate(), sedSynAccLoanVO.getLoanEndDate());
                //if (i == -1 || i == 0) {
                    accLoanVO.setSettlDate(sedSynAccLoanVO.getSettlementDate());
               // }else {
                    //accLoanVO.setSettlDate(LocalDate.parse(sedSynAccLoanVO.getSettlementDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd")).plusDays(-1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                //}
                return;
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("时间转换出错");
            }
        }
        accLoanVO.setSettlDate(sedSynAccLoanVO.getSettlementDate());
    }

    private void setBizDate(String sub_date_date, AccLoanVO accLoanVO) throws Exception {
        //如果放款时间大于文件日期则使用放款时间
        String firstDisbDate = accLoanVO.getFirstDisbDate();
        int i = TimeUtil.compareDates(accLoanVO.getFirstDisbDate(), batchSubDate);
        if (i == 1) {
            accLoanVO.setBizDate(firstDisbDate);
            return;
        }
        accLoanVO.setBizDate(sub_date_date);
    }

    private void setOverdueInfo(Map<String, LoanRepayPlanVO> loanRepayPlanVOMap, SynAccLoanVO sedSynAccLoanVO, AccLoanVO accLoanVO) {
        if (loanRepayPlanVOMap.get(sedSynAccLoanVO.getId()) != null) {
            // 逾期起始日  期数最小的逾期到期日
            accLoanVO.setCapOverdueDate(loanRepayPlanVOMap.get(sedSynAccLoanVO.getId()).getStmtDate());
        }else {
            if (StringUtils.isNotEmpty(accLoanVO.getCapOverdueDate())) {
                accLoanVO.setCapOverdueDate(null);
            }
        }
        ArrayList<String> refNbrParams = new ArrayList<>();
        refNbrParams.add(sedSynAccLoanVO.getId());
        List<LoanRepayPlanVO> repayPlanVOS = accLoanRepayPlanService.queryRepayPlansByRefNbr(refNbrParams);
        if (repayPlanVOS == null) {
            repayPlanVOS = new ArrayList<>();
        }
        // 当前逾期期数-查状态为逾期的还款计划数量
        accLoanVO.setOverTimesCurrent(new BigDecimal(repayPlanVOS.stream().filter(e->"O".equals(e.getStatus())).count()));
        // 累计逾期期数-查逾期过（is_over_due=1）还款计划的数量
        accLoanVO.setOverTimesTotal(new BigDecimal(repayPlanVOS.stream().filter(e->"1".equals(e.getIsOverDue())).count()));
        // 最高逾期期数-最高连续逾期的期数（查逾期过（is_over_due=1）的还款计划将 判断最大连续的个数）
        accLoanVO.setMaxTimesTotal(new BigDecimal(getMaxTimesTotal(repayPlanVOS.stream().filter(e->"1".equals(e.getIsOverDue())).collect(Collectors.toList()))));
    }

    /**
     * 将数据插入差异表
     *
     * @param diffType
     * @param synAccLoanVO
     * @param accLoanVO
     * @param msg 差异信息
     */
    private void insertDiffLog(String diffType, SynAccLoanVO synAccLoanVO, AccLoanVO accLoanVO, String msg) {
        SyncLoanDiffLogVO insertRecord = new SyncLoanDiffLogVO();
        insertRecord.setId(UUID.randomUUID().toString());
        insertRecord.setDataType(diffType);
        insertRecord.setCreateTime(new Date());
        insertRecord.setBatchRunTime(batchRunDate);
        insertRecord.setOpenDay(openDay);
        insertRecord.setBatchDay(batchSubDate);
        insertRecord.setHjId(synAccLoanVO.getId());
        insertRecord.setHjContNo(synAccLoanVO.getContNo());
        insertRecord.setHjLoanSeq(synAccLoanVO.getLoanSeq());
        insertRecord.setHjDistrNo(synAccLoanVO.getDistrNo());
        insertRecord.setHjPrdType(synAccLoanVO.getPrdType());
        insertRecord.setHjCusId(synAccLoanVO.getCusId());
        insertRecord.setHjLoanBalance(synAccLoanVO.getLoanBalance());
        insertRecord.setHjOutstandingPrincipal(synAccLoanVO.getOutstandingPrincipal());
        insertRecord.setHjOverduePrincipal(synAccLoanVO.getOverduePrincipal());
        insertRecord.setHjAmount(synAccLoanVO.getAmount());
        insertRecord.setHjOverdueInterest(synAccLoanVO.getOverdueInterest());
        insertRecord.setHjOverdueCharge(synAccLoanVO.getOverdueCharge());
        insertRecord.setHjCompIntRateInc(synAccLoanVO.getCompIntRateInc());
        insertRecord.setHjLoanStartDate(synAccLoanVO.getLoanStartDate());
        insertRecord.setHjLoanEndDate(synAccLoanVO.getLoanEndDate());
        insertRecord.setHjTlementDate(synAccLoanVO.getSettlementDate());
        insertRecord.setHjAccountstatus(synAccLoanVO.getAccountStatus());
        insertRecord.setHjRepayDate(synAccLoanVO.getRepayDate());
        insertRecord.setHjRepaymentMode(synAccLoanVO.getRepaymentMode());
        insertRecord.setHjIradjustMode(synAccLoanVO.getIrAdjustMode());
        insertRecord.setHjIssueMargin(synAccLoanVO.getIssueMargin());
        insertRecord.setHjRulingIr(synAccLoanVO.getRulingIr());
        insertRecord.setHjRealityIrY(synAccLoanVO.getRealityIrY());
        insertRecord.setHjFixedRateIrY(synAccLoanVO.getFixedRateIrY());
        insertRecord.setHjRaceIntCumu(synAccLoanVO.getRaceIntCumu());
        insertRecord.setHjUnpdArrsPrnBa1(synAccLoanVO.getUnpdArrsPrnBa1());
        insertRecord.setHjRaceReIntCumu(synAccLoanVO.getRaceReIntCumu());
        insertRecord.setHjCla(synAccLoanVO.getCla());
        insertRecord.setHjOveerdueDay(synAccLoanVO.getOveerdueDay());
        insertRecord.setHjAcctSt(synAccLoanVO.getAcctStatus());
        if (Objects.isNull(accLoanVO)) {
            syncLoanDiffLogVOS.add(insertRecord);
            return;
        }
        insertRecord.setWdApplySeq(accLoanVO.getApplySeq());
        insertRecord.setWdBizDate(accLoanVO.getBizDate());
        insertRecord.setWdLoanSeq(accLoanVO.getLoanSeq());
        insertRecord.setWdDistrNo(accLoanVO.getDistrNo());
        insertRecord.setWdCusId(accLoanVO.getCusId());
        insertRecord.setWdLoanStartDate(accLoanVO.getLoanStartDate());
        insertRecord.setWdLoanEndDate(accLoanVO.getLoanEndDate());
        insertRecord.setWdOrigExpiDate(accLoanVO.getOrigExpiDate());
        insertRecord.setWdRulingIr(accLoanVO.getRulingIr());
        insertRecord.setWdRealityIrY(accLoanVO.getRealityIrY());
        insertRecord.setWdAccountStatus(accLoanVO.getAccountStatus());
        insertRecord.setWdCapOverdueDate(accLoanVO.getCapOverdueDate());
        insertRecord.setWdOverTimesCurrent(accLoanVO.getOverTimesCurrent() != null ? accLoanVO.getOverTimesCurrent().toString() : "");
        insertRecord.setWdOverTimesTotal(accLoanVO.getOverTimesTotal() != null ? accLoanVO.getOverTimesTotal().toString() : "");
        insertRecord.setWdMaxTimesTotal(accLoanVO.getMaxTimesTotal() != null ? accLoanVO.getMaxTimesTotal().toString() : "");
        insertRecord.setWdSettlDate(accLoanVO.getSettlDate());
        insertRecord.setWdFixedRate(accLoanVO.getFixedRate());
        insertRecord.setWdLoanBanlance(accLoanVO.getLoanBalance());
        insertRecord.setWdOverdueBalance(accLoanVO.getOverdueBalance());
        insertRecord.setWdNormalBalance(accLoanVO.getNormalBalance());
        insertRecord.setWdUnpdPrinBal(accLoanVO.getUnpdPrinBal());
        insertRecord.setWdReceIntCumu(accLoanVO.getReceIntCumu());
        insertRecord.setWdDelayIntCumu(accLoanVO.getDelayIntCumu());
        insertRecord.setWdActualIntCumu(accLoanVO.getActualIntCumu());
        insertRecord.setWdUnpdArrPrnBal(accLoanVO.getUnpdArrPrnBal());
        insertRecord.setWdUnpdArrPrnBal1(accLoanVO.getUnpdArrPrnBal1());
        insertRecord.setWdActArrPrnBal(accLoanVO.getActArrPrnBal());
        insertRecord.setWdDelayIntCumu1(accLoanVO.getDelayIntCumu1());
        insertRecord.setWdUnpdArrsIntBal1(accLoanVO.getUnpdArrsIntBal1());
        insertRecord.setWdActArrsIntBal(accLoanVO.getActArrsIntBal());
        insertRecord.setWdReturnDate(accLoanVO.getReturnDate());
        insertRecord.setWdRepaymentMode(accLoanVO.getRepaymentMode());
        insertRecord.setWdClapre(accLoanVO.getClaPre());
        insertRecord.setWdCla(accLoanVO.getCla());
        insertRecord.setWdClaDatePre(accLoanVO.getClaDatePre());
        insertRecord.setWdClaDate(accLoanVO.getClaDate());
        insertRecord.setWdOverdueDays(accLoanVO.getOverdueDays() == null ? "" : accLoanVO.getOverdueDays().toString());
        insertRecord.setWdCurrTerm(accLoanVO.getCurrTerm() == null ? "" : accLoanVO.getCurrTerm().toString());
        insertRecord.setWdLastUpdateTime(accLoanVO.getLastUpdateTime());
        insertRecord.setWdBkCol6(msg);
        syncLoanDiffLogVOS.add(insertRecord);
        return;
    }


    /**
     * 判断账务日期时间是否小于当前的openday
     *
     * @param accLoanVO
     * @return
     */
    private boolean checkDate(AccLoanVO accLoanVO, SynAccLoanVO synAccLoanVO) {
        //如果借据的业务时间不小于当前的openday，代表是当天放的款，数据已经是最新的了，不做处理
        LocalDate openDayDate = LocalDate.parse(openDay, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        LocalDate bizeDate = LocalDate.parse(accLoanVO.getBizDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        LocalDate fileDate = LocalDate.parse(batchSubDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        if (bizeDate.until(openDayDate, ChronoUnit.DAYS) <= 0) {
            //保存不处理数据到差异表
            insertDiffLog("3", synAccLoanVO, accLoanVO,"bizDate和openDate校验不通过");
            return false;
        }
        //如果借据为结清状态，并且bizday<文件日期那么不做处理
        if (DblStEnum.ENUM_4.getValue().equals(accLoanVO.getAccountStatus())) {
            if (bizeDate.until(fileDate, ChronoUnit.DAYS) > 0) {
                insertDiffLog("3", synAccLoanVO, accLoanVO,"借据为结清状态，并且bizday小于文件日期");
                return false;
            }
        }
        return true;
    }

    /**
     * 获取逾期还款计划: <br>
     * 0.1:caoxin:2019/6/27 17:57: 获取逾期还款计划: <br>
     *
     * @return
     * @author caoxin
     * @date 2019/6/27 17:57
     * @version 0.1
     * @since 2019/6/27 17:57
     */
    private List<LoanRepayPlanVO> getOverLoanRepayPlan(SynAccLoanVO sedSynAccLoanVO) {
        LoanRepayPlanVO loanRepayPlanVO = new LoanRepayPlanVO();
        loanRepayPlanVO.setRefNbr(sedSynAccLoanVO.getId());
        return Optional.ofNullable(accLoanRepayPlanService.queryRepayPlanByRefNbrAndStatus(loanRepayPlanVO)).orElseGet(ArrayList::new);
    }

    private List<LoanRepayPlanVO> queryRepayPlanByRefNbrAndIsOverDue(SynAccLoanVO sedSynAccLoanVO) {
        LoanRepayPlanVO loanRepayPlanVO = new LoanRepayPlanVO();
        loanRepayPlanVO.setRefNbr(sedSynAccLoanVO.getId());
        return Optional.ofNullable(accLoanRepayPlanService.queryRepayPlanByRefNbrAndIsOverDue(loanRepayPlanVO)).orElseGet(ArrayList::new);
    }

    /**
     * 判断最高连续逾期次数: <br>
     * 0.1:caoxin:2019/6/27 18:50: 判断最高连续逾期次数 <br>
     *
     * @return
     * @author caoxin
     * @date 2019/6/27 18:50
     * @version 0.1
     * @since 2019/6/27 18:50
     */
    private int getMaxTimesTotal(List<LoanRepayPlanVO> list) {
        if (list == null) {
            return 0;
        }
        if (list.size() <= 1) {
            return list.size();
        }
        //将list排序
        List<LoanRepayPlanVO> collect = list.stream().sorted(Comparator.comparingInt(LoanRepayPlanVO::getTerm)).collect(Collectors.toList());
        int maxSucc = 1;
        int temp = 1;
        for (int i = 1; i < collect.size(); i++) {
            if ((collect.get(i).getTerm() - 1) == collect.get(i - 1).getTerm()) {
                temp++;
            } else {
                if (temp > maxSucc) {
                    maxSucc = temp;
                }
                temp = 1;
            }
        }
        return maxSucc > temp ? maxSucc : temp;
    }

    /**
     * 更新额度
     *
     * @param applyseqs 用信申请流水号集合
     */
    private void updateLimit(List<String> applyseqs) throws Exception {
        if (applyseqs == null) {
            return;
        }
        if (applyseqs.isEmpty()) {
            return;
        }
        List<List<String>> partition = ListUtils.partition(applyseqs, 500);
        for (List<String> strings : partition) {
            //根据用信流水号获取授信流水号
            List<NlsApplyInfoVO> nlsApplyInfoVOS = nlsApplyInfoService.queryByApplySeqs(strings);
            //循环更新额度
            for (NlsApplyInfoVO nlsApplyInfoVO : nlsApplyInfoVOS) {
                if (YedConstantSet.prdId.equals(nlsApplyInfoVO.getPrdCode())){
                    updateLmtPrdContService.updateLmtProYed(nlsApplyInfoVO.getLmtApplySeq(), nlsApplyInfoVO.getApplySeq());
                }else{
                    updateLmtPrdContService.updateLmtPro(nlsApplyInfoVO.getLmtApplySeq(), nlsApplyInfoVO.getApplySeq());
                }
            }
        }

    }

    private int getCurrentTerm(AccLoanVO accLoanVO) {
        Integer integer = accLoanRepayPlanService.queryCurrentTerm(accLoanVO.getBizDate(), accLoanVO.getBillNo());
        if (integer == null) {
            return 0;
        }
        return integer.intValue();
    }

    public void insertTaxRecord(SynAccLoanVO synAccLoanVO, String subDate) {
        try {
            PsdSendTaxRecordVO psdSendTaxRecordVO = new PsdSendTaxRecordVO();
            psdSendTaxRecordVO.setTaxNo("");
            psdSendTaxRecordVO.setApplySeq(synAccLoanVO.getId());
            psdSendTaxRecordVO.setApplyStatus("Y");
            psdSendTaxRecordVO.setApplyMsg("自动扣款成功");
            psdSendTaxRecordVO.setSendType("5");
            psdSendTaxRecordVO.setBizDate(subDate);
            psdSendTaxRecordVO.setHandStatus("N");
            psdSendTaxRecordVO.setHandNum(0);
            psdSendTaxRecordVO.setCreateTime(new Date());
            psdSendTaxRecordService.insert(psdSendTaxRecordVO);
        } catch (Exception ex) {
            logger.error("还款成功插入回写税局表发生异常", ex);
        }
    }

}

